package cn.chenfeifx.checker.thread;

import cn.chenfeifx.checker.CheckerApp;
import cn.chenfeifx.checker.eneity.ExportDataModel;
import cn.chenfeifx.checker.eneity.MessageEntity;
import cn.chenfeifx.checker.eneity.Report;
import cn.chenfeifx.checker.eneity.ReportEntity;
import cn.chenfeifx.checker.enums.CheckerEnum;
import cn.chenfeifx.checker.util.DateUtil;
import cn.chenfeifx.checker.util.ImageBlankChecker;
import cn.chenfeifx.checker.util.MD5Checker;
import cn.chenfeifx.checker.util.SmartImageUtil;
import cn.chenfeifx.core.controls.CFTableView;
import com.alibaba.excel.util.StringUtils;
import javafx.scene.control.TableView;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class CheckRunable implements Runnable {

    private String filePath;
    private Report report;
    private Integer index;

    private static final Map<String, Set<Map<String, String>>> dataMap = new ConcurrentHashMap<>();

    public CheckRunable(Integer index, Report report, String filePath) {
        this.index = index;
        this.filePath = filePath;
        this.report = report;
    }


    @Override
    public void run() {
        List<MessageEntity> messageList = new ArrayList<MessageEntity>();
        String reference = report.getReference();

        ExportDataModel exportDataModel = new ExportDataModel();
        exportDataModel.setArchiveId(reference);

        exportDataModel.setFileIntegrity("√");
        exportDataModel.setFileAccuracy("√");
        exportDataModel.setMaterialCatalogAccuracy("√");
        exportDataModel.setMaterialCatalogIntegrity("√");
        exportDataModel.setMaterialCatalogMatching("√");
        exportDataModel.setPictureClarity("√");

        exportDataModel.setPictureMatching("√");
        exportDataModel.setPictureRepeatability("√");
        exportDataModel.setMaterialCatalogRepeatability("√");
        if (StringUtils.isEmpty(report.getCompleteNumber()) ||
                StringUtils.isEmpty(report.getCategoryNumber()) ||
                StringUtils.isEmpty(report.getCaseFileNumber()) ||
                StringUtils.isEmpty(report.getReference()) ||
                StringUtils.isEmpty(report.getTitleName()) ||
                report.getCaseNumber() == null ||
                report.getPageNumber() == null ||
                StringUtils.isEmpty(report.getYear()) ||
                StringUtils.isEmpty(report.getTerm()) ||
                //StringUtils.isEmpty(report.getSecurity()) ||
                StringUtils.isEmpty(report.getOpenState())
                //StringUtils.isEmpty(report.getRemark())
        ) {
            messageList.add(new MessageEntity(reference, "案卷目录不全"));
            System.out.println(reference + "案卷目录不全");
            exportDataModel.setFileIntegrity("✖");
            CheckerApp.getInstance().setMessageList(CheckerEnum.FILES.getCode(), messageList);
            CFTableView cfTableView = CheckerApp.getInstance().getCfTableView();
            TableView tableView = cfTableView.getTableView();
            List<Report> items = tableView.getItems();
            Report report1 = items.get(index - 1);
            report1.setStatusPath("/img/cha.png");
            cfTableView.refresh();
        }

        boolean checkYear = DateUtil.checkYear(report.getYear());
        if (!checkYear) {
            messageList.add(new MessageEntity(reference, "卷内年度格式不正确"));
            exportDataModel.setMaterialCatalogAccuracy("✖");
        }



        Integer pagenumber = 0;
        try {

            Set<Map<String, String>> dataList = getDataByReference(reference, exportDataModel, messageList);
            if(dataList == null || dataList.isEmpty()){
                messageList.add(new MessageEntity(reference, "卷内不能为空"));
                exportDataModel.setMaterialCatalogIntegrity("✖");
            }else {
                for (Map<String, String> map : dataList) {
                    Set<String> keys = map.keySet();
                    for (String key : keys) {
                        String value = map.get(key);
                        if(StringUtils.isBlank(value) && !key.equals("备注") && !key.equals("密级")){
                            messageList.add(new MessageEntity(reference, key+"不能为空,卷内顺序号为: "+map.get("卷内顺序号")));
                            exportDataModel.setMaterialCatalogIntegrity("✖");
                        }else {
                            if (key.equals("日期")) {
                                boolean flag = checkDate(value);
                                if(!flag){
                                    messageList.add(new MessageEntity(reference, "日期格式不正确"));
                                    exportDataModel.setMaterialCatalogAccuracy("✖");
                                }
                            }
                        }
                    }
                }
            }

            //Set<Map<String,String>> numberset = new HashSet<>();
            List<String> newFilenames = new ArrayList<>();

            Set<String> knownHashes = new HashSet<>();

           /*Path dir = Paths.get(filePath);
            Path parent = dir.getParent();
            URI uri = parent.toUri();
            String urlStr = uri.toString();
             String url = urlStr + "/图片"
                    + report.getReference();*/
            String url = filePath+"/"+report.getReference();


            List<String> fileNames = new ArrayList<>();
            Set<String> caseNumbers = new HashSet<>();
            //获取档号路径下所有的图片
            File folder = new File(url);
            if (folder.exists()) {
                File[] fileList = folder.listFiles();
                if (fileList != null) {
                    for (File filedir : fileList) {
                        String fileName = filedir.getName();
                        if(isImageFile(fileName)) {
                            fileNames.add(fileName);
                            String path = filedir.getPath();
                            newFilenames.add(path);
                            pagenumber++;
                            String caseNumber = getCaseNumber(fileName);
                            caseNumbers.add(caseNumber);
                        }
                        /*File[] imageFiles = filedir.listFiles();
                        if (imageFiles != null) {
                            for (File imageFile : imageFiles) {
                                if (isImageFile(imageFile.getName())) {
                                    //HashMap<String, String> map = new HashMap<>();
                                    //map.put(imageFile.getPath(), imageFile.getName());
                                    //numberset.add(map);
                                    String fileName = imageFile.getName();
                                    fileNames.add(fileName);
                                    String path = imageFile.getPath();
                                    newFilenames.add(path);
                                    pagenumber++;
                                }
                            }
                        }*/

                    }
                }
            }


            if (!newFilenames.isEmpty()) {
                for (String newname : newFilenames) {
                    boolean b = checkImage(reference, newname, knownHashes, messageList, exportDataModel);
                }
            }

            //图片排序
            checkSequenceContinuity(fileNames, reference, messageList, exportDataModel);

            // 件数
            //int folderCount = getSubFolderCount(url);
            System.out.println(reference + "件数: " + caseNumbers.size());
            exportDataModel.setMaterialCatalogCount(caseNumbers.size()+"");
            if (caseNumbers.size() != report.getCaseNumber()) {
                exportDataModel.setMaterialCatalogIntegrity("✖");
                exportDataModel.setMaterialCatalogAccuracy("✖");
                messageList.add(new MessageEntity(reference, "案卷目录件数不对"));
            }

            if (newFilenames.size() != report.getPageNumber()) {
                exportDataModel.setPictureMatching("✖");
                exportDataModel.setMaterialCatalogMatching("✖");
                exportDataModel.setMaterialCatalogIntegrity("✖");
                //exportDataModel.setPictureClarity("✖");
                messageList.add(new MessageEntity(reference, "案卷目录页数不对"));
            }

        } /*catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }*/ catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        /*for (MessageEntity messageEntity : messageList) {
            System.out.println(messageEntity.getMessage());
            CheckerApp.getInstance().getMessageList(CheckerEnum.FILES.getCode()).add(messageEntity);
        }*/
        CheckerApp.getInstance().setMessageList(CheckerEnum.FILES.getCode(), messageList);
        exportDataModel.setPictureCount(pagenumber);
        //CheckerApp.getInstance().getReports(CheckerEnum.FILES.getCode()).add(exportDataModel);
        CheckerApp.getInstance().setReport(CheckerEnum.FILES.getCode(), exportDataModel);
        CFTableView cfTableView = CheckerApp.getInstance().getCfTableView();
        TableView tableView = cfTableView.getTableView();
        List<Report> items = tableView.getItems();
        Report report1 = items.get(index - 1);
        report1.setStatusPath("/img/right.png");
        cfTableView.refresh();
    }

    private Set<Map<String, String>> getDataByReference(String reference, ExportDataModel exportDataModel, List<MessageEntity> messageList) {
        if(dataMap == null ||dataMap.isEmpty()) {
            try {
                getExcelData(reference, exportDataModel, messageList);
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("系统异常: " + e.getMessage());
            }
        }
        return dataMap.get(reference);
    }

    private synchronized void getExcelData(String reference,ExportDataModel exportDataModel,List<MessageEntity> messageList) throws Exception{
        File file = new File(filePath);
        FilenameFilter filenameFilter = (dir, name) -> name.contains("卷内") && name.endsWith(".xlsx");
        File[] files = file.listFiles(filenameFilter);
        if (files == null || files.length == 0) {
            messageList.add(new MessageEntity(reference, "卷内目录不存在"));
            exportDataModel.setFileIntegrity("✖");
        }else {
            File fileDir = files[0];
            if (fileDir.exists() && fileDir.canRead()) {
                FileInputStream excelFile = new FileInputStream(fileDir);
                XSSFWorkbook workbook = new XSSFWorkbook(excelFile);
                XSSFSheet sheet = workbook.getSheetAt(0);

                //获取表头数据
                //获取第二行表头名称
                /*Row header = sheet.getRow(1);
                //获取案卷题名数据
                String titleNameDataValue = header.getCell(2).getStringCellValue();
                if (StringUtils.isBlank(titleNameDataValue)) {
                    exportDataModel.setMaterialCatalogIntegrity("✖");
                    messageList.add(new MessageEntity(reference, "卷内目录案卷题名不能为空"));
                }
                //获取档号数据
                String referenceDataValue = header.getCell(5).getStringCellValue();
                if (StringUtils.isBlank(referenceDataValue)) {
                    exportDataModel.setMaterialCatalogIntegrity("✖");
                    messageList.add(new MessageEntity(reference, "卷内目录档号不能为空"));
                }*/

                Map<Integer,String> columnNames = new HashMap<>();

                Row header = sheet.getRow(0);
                for (int i = 0; i <=14; i++) {
                    String stringCellValue = header.getCell(i).getStringCellValue();
                    columnNames.put(i,StringUtils.isEmpty(stringCellValue) ? "" : stringCellValue);
                }


                //从第二行开始读取(索引为1)
                List<Map<String,String>> dataList = new ArrayList<>();
                int lastRowNum = sheet.getLastRowNum();
                for (int rowIndex = 1; rowIndex <= lastRowNum; rowIndex++) {
                    Row row = sheet.getRow(rowIndex);
                    if (row != null) {
                        Map<String,String> rowData = new HashMap<>();
                        for (int cellIndex = 0; cellIndex <=14; cellIndex++) {
                            Cell cell = row.getCell(cellIndex);
                            String cellValue = getCellValueAsString(cell).trim();
                            rowData.put(columnNames.get(cellIndex),cellValue);
                            dataList.add(rowData);
                        }


                        String catalogName = rowData.get("档号");

                        dataMap.computeIfAbsent(catalogName,k -> new HashSet<>()).add(rowData);

                    }
                }
            }

        }

    }

    private Boolean getFlag(String str, List<MessageEntity> messageEntityList) {
        return messageEntityList.stream()
                .anyMatch(messageEntity -> messageEntity.getMessage() != null && messageEntity.getMessage().contains(str));
    }

    private static boolean checkImage(String reference, String path, Set<String> knownHashes, List<MessageEntity> messageList, ExportDataModel exportDataModel) {
        boolean picNotReadable = false;
        boolean picRepeat = false;
        boolean picBlank = false;
        boolean picDpi = false;
        boolean picColorDepth = false;
        boolean isValidFileName = false;
        Path startPath = Paths.get(path);
        // 检查路径是否存在
        if (Files.exists(startPath)) {
            try {
                System.out.println(path);
                String filepath = path.toString();
                //校验图片命名是否合规
                String[] picNames = filepath.split("\"");
                String picName = picNames[picNames.length - 1];
                if (!isValidFileName(picName)) {
                    messageList.add(new MessageEntity(reference, path + "图片文件命名不合规"));
                    exportDataModel.setFileIntegrity("✖");
                    isValidFileName = true;
                }
                String fileMD5 = MD5Checker.getFileMD5(path.toString());
                // 检查MD5哈希值是否表示文件重复
                if (knownHashes.contains(fileMD5)) {
                    messageList.add(new MessageEntity(reference, path + " 文件重复"));
                    exportDataModel.setMaterialCatalogRepeatability("✖");
                    exportDataModel.setPictureRepeatability("✖");
                    picRepeat = true;
                } else {
                    knownHashes.add(fileMD5);
                }
                //判断图片是否可读
                boolean imageReadable = SmartImageUtil.isImageReadable(path.toString());
                if (!imageReadable) {
                    messageList.add(new MessageEntity(reference, path + " 图片不可读"));
                    picNotReadable = true;
                    exportDataModel.setPictureMatching("✖");

                } else {
                    //判断图片是否为空白
                    boolean imageBlank = ImageBlankChecker.isImageBlank(path.toString(), 10);
                    if (imageBlank) {
                        messageList.add(new MessageEntity(filepath, "图片空白"));
                        picBlank = true;
                        exportDataModel.setPictureMatching("✖");

                    }

                    if (!SmartImageUtil.checkPPI(path.toString())) {
                        messageList.add(new MessageEntity(filepath, "图片DPI不达标"));
                        picDpi = true;
                        exportDataModel.setPictureClarity("✖");

                    }
                    if (!SmartImageUtil.checkColorDepth(path.toString())) {
                        messageList.add(new MessageEntity(filepath, "图片颜色深度不达标"));
                        exportDataModel.setPictureClarity("✖");
                        picColorDepth = true;
                    }

                }

                //判断图片是否有黑边
                boolean flag = SmartImageUtil.detectBlackBorder(path.toString());
                if (flag) {
                    messageList.add(new MessageEntity(filepath,"图片有黑边"));
                    exportDataModel.setPictureClarity("✖");
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
            if (picNotReadable || picRepeat || picBlank || picDpi || picColorDepth || isValidFileName) {
                return false;
            }

        } else {
            exportDataModel.setMaterialCatalogAccuracy("✖");
            messageList.add(new MessageEntity(reference, startPath + " 路径不存在，文件夹为空。"));
        }
        return true;
    }

    private static String getCellValueAsString(Cell cell) {
        if (cell == null) {
            return "";
        }
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                // 处理数字类型，包括日期（日期在Excel中也是以数字形式存储）
                if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
                    // 将日期格式化为字符串
                    java.util.Date date = cell.getDateCellValue();
                    java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    return dateFormat.format(date);
                } else {
                    double numericCellValue = cell.getNumericCellValue();
                    String result = String.format("%.0f", numericCellValue);
                    // 将数字转换为字符串
                    return result;
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                try {
                    // 计算公式并转换为字符串
                    return String.valueOf(cell.getNumericCellValue());
                } catch (Exception e) {
                    return cell.getStringCellValue();
                }
            default:
                return "";
        }
    }


    public static boolean checkDate(String dateString) {
        if (dateString.equals("000000")) {
            return true;
        }
        if (dateString.endsWith("00")) {
            return true;
        }
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
        try {
            LocalDate.parse(dateString, dtf);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    public static String getCaseNumber(String filename) {
        // 正则表达式：匹配最后一组6个数字
        Pattern pattern = Pattern.compile("(\\d{3})\\d{3}\\.jpg$");
        Matcher matcher = pattern.matcher(filename);

        if (matcher.find()) {
            return matcher.group(1); // 返回匹配的前三个数字
        }
        return null; // 如果没有匹配到，返回null
    }


    public static void checkSequenceContinuity(List<String> fileNames, String reference, List<MessageEntity> messageList, ExportDataModel exportDataModel) {
        System.out.println("图片顺序号排序检测开始");
        // 使用TreeMap保存文件名和序号
        List<String> sequenceList = new ArrayList<>();

        for (String fileName : fileNames) {
            String[] str = fileName.split("-");
            String s = str[str.length - 1];
            String substring = s.substring(0, s.length() - 4);
            sequenceList.add(substring.substring(substring.length() - 3));
        }

        Collections.sort(sequenceList);

        for (int i = 1; i < sequenceList.size(); i++) {
            int prevSeq = Integer.parseInt(sequenceList.get(i - 1));
            int currentSeq = Integer.parseInt(sequenceList.get(i));
            int poor = currentSeq - prevSeq;
            if (currentSeq != prevSeq + 1) {
                if (poor > 1) {
                    for (int j = 1; j < poor; j++) {
                        messageList.add(new MessageEntity(reference, "图片编号顺序不连续,缺少" + String.format("000%d", prevSeq + j)));
                        exportDataModel.setFileIntegrity("✖");
                    }
                } else {
                    messageList.add(new MessageEntity(reference, "图片编号顺序不连续,缺少" + String.format("000%d", prevSeq + 1)));
                    exportDataModel.setFileIntegrity("✖");
                }
            }
        }
        System.out.println("图片顺序号排序检测结束");
    }

    public static String replaceString(String str) {
        str = str.replace("一", "1");
        str = str.replace("二", "2");
        str = str.replace("三", "3");
        str = str.replace("四", "4");
        str = str.replace("五", "5");
        str = str.replace("六", "6");
        str = str.replace("七", "7");
        str = str.replace("八", "8");
        str = str.replace("九", "9");
        str = str.replace("十", "10");
        return str;
    }

    private static boolean isImageFile(String name) {
        String imageExtension = name.toLowerCase();
        return imageExtension.endsWith(".jpg") ||
                imageExtension.endsWith(".jpeg") ||
                imageExtension.endsWith(".png") ||
                imageExtension.endsWith(".gif");
    }

    // 校验文件名称格式是否符合 "A143-1·3·1-0001-004012.jpg" 格式
    public static boolean isValidFileName(String fileName) {

        String fileNameRegex = "([^\\\\\\\\]+)$";

        Pattern pattern = Pattern.compile(fileNameRegex);
        Matcher matcher = pattern.matcher(fileName);

        if (matcher.find())
            fileName = matcher.group(1);


        // 正则表达式，匹配 "A046-1·2017·1-0001001.JPG" 格式
        // 正则表达式模式
        //String regex = "^A\\d{3}-\\d{1}·\\d{4}-\\d{1}-\\d{4}-\\d{3}\\.(JPG|jpg)$";
        //String regex = "^A\\d{3}-\\d·\\d{4}·\\d-\\d{7}\\.(?i)jpg$";
        //String regex = "^AY\\d{3}-\\d{1}·\\d{1}-\\d{3}-\\d{6}\\.jpg$";
        //String regex = "^([A-Za-z]{2})\\d{3}-\\d{1}·\\d{1}-\\d{3}-\\d{3}-\\d{3}\\.jpg$";
        //String regex = "^[A-Z]{1}\\d{3}-\\d{1}·\\d{1}-\\d{4}-\\d{6}\\.jpg$";
        //String regex = "^[A-Z]{1}\\d{3}-\\d{1}·\\d{1}·\\d{1}-\\d{4}-\\d{6}\\.jpg$";
        //String regex = "^[A-Z]{1}\\d{3}-\\d{1}·\\d{4}·\\d{1}-\\d{7}\\.jpg$";
        String regex = "^[A-Z]{1}\\d{3}-\\d{1}·\\d{1}·\\d{1}-\\d{4}-\\d{6}\\.jpg$";
        pattern = Pattern.compile(regex);
        matcher = pattern.matcher(fileName);
        return matcher.matches();
    }

    public static int getSubFolderCount(String url) {
        File folder = new File(url);
        File[] files = folder.listFiles();
        int count = 0;
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    count++;
                }
            }
        }
        return count;
    }


    public static void main(String[] args) {
        //String regex = "^AY\\d{3}-\\d{1}·\\d{1}-\\d{3}-\\d{6}\\.jpg$";
        //String regex = "^AY\\d{3}-\\d{1}·\\d{1}-\\d{3}-\\d{6}\\.jpg$";
        //String regex = "^([A-Za-z]{2})\\d{3}-\\d{1}·\\d{1}-\\d{3}-\\d{3}-\\d{3}\\.jpg$";
        String regex = "^[A-Z]{1}\\d{3}-\\d{1}·\\d{4}·\\d{1}-\\d{7}\\.jpg$";

        //String url = "d2efef860d4f8761307ab125b927f018";


       /* String fileName1 = "C:/Users/ji363/Desktop/新建文件夹/1·1/AY010-1·1-010/0001/AY010-1·1-010-001-001.jpg";

        String fileName2 = "C:/Users/ji363/Desktop/新建文件夹/1·1/AY010-1·1-010/0002/AY010-1·1-010-002007.jpg";

        String fileMD5 = MD5Checker.getFileMD5(fileName1);

        String fileMD52 = MD5Checker.getFileMD5(fileName2);*/

        // 测试文件名
        //String fileName = "AY010-1·1-009-001001.jpg";
        String fileName = "A143-1·1998·3-0001001.jpg";

        // 创建正则表达式模式
        Pattern pattern = Pattern.compile(regex);

        // 创建匹配器
        Matcher matcher = pattern.matcher(fileName);

        // 判断是否匹配
        if (matcher.matches()) {
            System.out.println("文件名有效");
        } else {
            System.out.println("文件名无效");
        }
    }

}
